<?php
include "Test.php";
class DependencyInjectionContainer
{
    private $bindings = [];

    /**
     * 绑定接口和实现类
     * @param $abstract
     * @param $concrete
     */
    public function bind($abstract, $concrete)
    {
        $this->bindings[$abstract] = $concrete;
    }

    // 根据接口获取实例
    public function make($abstract)
    {
        if (isset($this->bindings[$abstract])) {
            $concrete = $this->bindings[$abstract];
            if (is_callable($concrete)) {//检查指定的变量是否可以被调用
                return call_user_func($concrete, $this);
            } else {
                return new $concrete;
            }
        }
        throw new Exception("No binding found for $abstract");
    }
}

$container = new DependencyInjectionContainer();
$container->bind("Test",Test::class);
//获取实例
$callBack = $container->make("Test");
print_r($callBack->call());

/*
 依赖注入容器有以下一些常见的应用场景：
大型 Web 应用：在复杂的 Web 应用中，有众多的服务、控制器、模型等组件，依赖注入容器可以有效地管理它们之间的依赖关系，使代码结构更清晰，易于维护和扩展。
框架开发：许多 PHP 框架都使用依赖注入容器来管理框架核心组件以及用户自定义的组件之间的依赖。
微服务架构：当构建微服务系统时，每个微服务可能有多个依赖，依赖注入容器可以帮助组织和管理这些依赖。
单元测试：通过在测试中配置依赖注入容器，可以轻松地为被测试的对象提供模拟的依赖，提高测试的可控性和可重复性。
模块式开发：当项目被划分为多个模块时，依赖注入容器可以协调不同模块之间的依赖，确保模块之间的解耦和独立开发。
配置管理：可以将依赖的配置信息与依赖注入容器结合，根据不同的环境（开发、生产等）动态地注入不同的依赖实现。
多人协作项目：有助于新加入的开发者快速理解和处理组件之间的依赖关系，提高团队协作效率。
例如，在一个电商网站中，订单处理服务需要依赖支付服务、库存服务和物流服务。通过依赖注入容器，可以方便地管理和注入这些依赖，
使得订单处理服务的代码更加简洁和专注于核心业务逻辑。
 */